package com.apobates.forum.member.api.dao;

import java.time.LocalDateTime;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Stream;
import com.apobates.forum.member.entity.Member;
import com.apobates.forum.member.entity.MemberGroupEnum;
import com.apobates.forum.member.entity.MemberRoleEnum;
import com.apobates.forum.member.entity.MemberStatusEnum;

/**
 * 会员的持久层接口
 * 
 * @author xiaofanku
 * @since 20190304
 */
public interface MemberDao {
	/**
	 * 创建新的会员
	 * 
	 * @param member 会员属性实例
	 */
	void save(Member member);

	/**
	 * 根据会员的登录帐号模糊查询会员
	 * 
	 * @param namesWordChar 会员帐号的字符
	 * @param showSize      显示的数量
	 * @return
	 */
	Stream<Member> searchByNames(String namesWordChar, int showSize);
	
	/**
	 * 根据会员的登录帐号模糊查询会员
	 * 
	 * @param namesWordChar 会员帐号的字符
	 * @return
	 */
	Stream<Member> searchByNames(String namesWordChar);
	
	/**
	 * 查看指定集合的会员信息
	 *  
	 * @param idList
	 * @return
	 */
	Stream<Member> findAllByIdList(List<Long> idList);
	
	/**
	 * 查看最近注册的会员
	 * 
	 * @param size 显示的数量
	 * @return
	 */
	Stream<Member> findAllOfRecent(int size);
	
	/**
	 * 查看指定的会员
	 * 
	 * @param memberNames 会员的登录帐号
	 * @param encryptPswd 加密后的登录密码
	 * @return
	 */
	Optional<Member> findOne(String memberNames, String encryptPswd);

	/**
	 * 
	 * @param memberNames
	 * @param encryptPswd
	 * @return
	 */
	Optional<Member> findOneForAdmin(String memberNames, String encryptPswd);

	/**
	 * 查看指定的会员
	 * 
	 * @param memberId 会员ID
	 * @return
	 */
	Member findOneById(long memberId);
	
	/**
	 * 更新会员的状态
	 * 
	 * @param status Key = 会员ID, Value = 更新的会员状态
	 * @return
	 */
	int editMemberStatus(Map<Long,MemberStatusEnum> status);
	
	/**
	 * 查看会员的头像
	 * 
	 * @param id 会员ID
	 * @return
	 */
	Optional<String> getAvatar(long id);
	
	/**
	 * 会员登录的帐号是否存在
	 * 
	 * @param memberNames 会员登录帐号
	 * @return 如果存在返回会员当前的密码盐
	 */
	Optional<String> findSalt(String memberNames);
	
	/**
	 * 查看指定的会员是否存在
	 * 
	 * @param id 会员ID
	 * @return 如果存在返回会员当前的密码盐
	 */
	Optional<String> findSalt(long id);
	
	/**
	 * 更新会员的头像地址
	 * 
	 * @param id               会员ID
	 * @param encodeAvatarPath 编码后的头像地址
	 * @return
	 */
	Optional<Boolean> editAvatar(long id, String encodeAvatarPath);

	/**
	 * 更新会员的昵称和签名
	 * 
	 * @param id        会员ID
	 * @param nickname  会员昵称
	 * @param signature 会员签名
	 * @return
	 */
	Optional<Boolean> editNicknameAndSignature(long id, String nickname, String signature);
	// 改变状态
	// 改变组
	
	/**
	 * 更新会员的管理角色
	 * 
	 * @param memberId 会员ID
	 * @param role     角色
	 * @return
	 */
	boolean editMemberRole(long memberId, MemberRoleEnum role);
	
	/**
	 * 更新会员的组
	 * 
	 * @param memberId 会员ID
	 * @param group    会员组
	 * @return
	 */
	boolean editMemberGroup(long memberId, MemberGroupEnum group);
	
	/**
	 * 更新会员的状态
	 * 
	 * @param memberId 会员ID
	 * @param status   更新的会员状态
	 * @return
	 */
	boolean editMemberStatus(long memberId, MemberStatusEnum status);
	
	/**
	 * 会员登录的帐号是否存在
	 * 
	 * @param memberNames 会员登录帐号
	 * @return 存在返回会员ID,不存在返回0,参数不可用返回-1
	 */
	long exists(String memberNames);

	/**
	 * 更新会员的登录密码
	 * 
	 * @param id             会员ID
	 * @param oldEncryptPswd 现在使用的密码,加密后的
	 * @param newEncryptPswd 更新的新密码,加密后的
	 * @param newPswdSalt    更新密码使用的盐
	 * @return
	 */
	int editPswd(long id, String oldEncryptPswd, String newEncryptPswd, String newPswdSalt);

	/**
	 * 重置会员的登录密码
	 * 
	 * @param id             会员ID
	 * @param newEncryptPswd 更新的新密码,加密后的
	 * @param newPswdSalt    更新密码使用的盐
	 * @return
	 */
	int resetPswd(long id, String newEncryptPswd, String newPswdSalt);
	
	/**
	 * 会员总数
	 * 
	 * @return
	 */
	long count();
	
	/**
	 * 统计指定日期范围内会员注册的数量
	 * 
	 * @param start  开始日期
	 * @param finish 结束日期
	 * @return Key = YYYY-MM-DD, Value=注册数
	 */
	TreeMap<String, Long> groupMemberForBirthDate(LocalDateTime start, LocalDateTime finish);
	
	/**
	 * 分组统计不同状态的会员数量
	 * 
	 * @return Key=Member.status, Value=会员数量
	 */
	EnumMap<MemberStatusEnum, Long> groupMemberForStatus();
	
	/**
	 * 分组统计不同角色的会员数量
	 * 
	 * @return Key=Member.mrole, Value=会员数量
	 */
	EnumMap<MemberRoleEnum, Long> groupMemberForRole();
	
	/**
	 * 分组统计不同组的会员数量
	 * 
	 * @return Key=Member.mgroup, Value=会员数量
	 */
	EnumMap<MemberGroupEnum, Long> groupMemberForGroup();
}
